package com.amkai.aes.webservice.binary.objecthandler.registration;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import com.amkai.aes.aescommon.service.binary.job.registration.PmCaseJob;
import com.amkai.aes.aescommon.service.binary.job.registration.PmCaseJobResult;
import com.amkai.aes.generatedbeans.billingledger.additionalcodes.ConditionCode;
import com.amkai.aes.generatedbeans.billingledger.additionalcodes.NoteInformation;
import com.amkai.aes.generatedbeans.billingledger.additionalcodes.OccurrenceCodeDate;
import com.amkai.aes.generatedbeans.billingledger.additionalcodes.OccurrenceSpanCodeDate;
import com.amkai.aes.generatedbeans.billingledger.additionalcodes.SupplementalInformation;
import com.amkai.aes.generatedbeans.billingledger.additionalcodes.ValueCodeAmount;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.time.AdmissionTimeLog;
import com.amkai.aes.generatedbeans.organization.Department;
import com.amkai.aes.generatedbeans.pmcase.PmCase;
import com.amkai.aes.generatedbeans.pmcase.PmCaseDetails;
import com.amkai.aes.server.manager.RegistrationManager;
import com.amkai.aes.server.util.AesServerUtils;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;
import com.amkai.rad.designerbase.beans.ChangedKind;
import com.amkai.aes.generatedbeans.pmcase.*;

//DP > http://jira.amkai.com:8080/browse/AES-13966

public class PmCaseJobHandler implements
		JobObjectHandler<PmCaseJob, Serializable, PmCaseJobResult> {

	@Override
	public PmCaseJobResult process(PmCaseJob job, Serializable object)
			throws Exception {
		PmCaseJobResult result = new PmCaseJobResult();
		switch (job.getKind()) {
		case LOAD:
			result.setPmCase(loadPmCase(job.getPmCaseId()));
			break;
		case SAVE:
			saveCase(job.getModuleDepartment(), job.getPmCase());
			break;
		}

		return result;
	}

	private void saveCase(Department moduleDepartment, PmCase pmCase) throws Exception {
		SessionManager sm = SiteManager.Start();
		HashMap<Integer, Long> createdItemIds = new HashMap<Integer, Long>();
		if (pmCase != null) {
			if (pmCase.getCaseDetails() != null) {
				try {
					sm.openTransaction();
					if (pmCase.getId() != null
							&& pmCase.getCaseDetails().getChangedProperties() != null
							&& pmCase
									.getCaseDetails()
									.getChangedProperties()
									.containsKey(
											PmCaseDetails.PROPERTYNAME_ADMISSIONHOUR)) {
						// KKORNEL: AES-13588
						Long caseHistoryAdmissionTimeLogId = (Long) sm
								.execute(
										"SELECT admissionTimeLog.id FROM CdmCaseHistory WHERE pmCase.id = :pmCaseID")
								.setLong("pmCaseID", pmCase.getId()).uniqueResult();

						if (caseHistoryAdmissionTimeLogId != null) {
							AdmissionTimeLog admissionTimeLog = sm.get(
									AdmissionTimeLog.class,
									caseHistoryAdmissionTimeLogId);

							Date admissionTime = null;

							if (pmCase.getCaseDetails().getAdmissionHour() != null) {
								Calendar c = Calendar.getInstance();
								c.set(Calendar.AM_PM, Calendar.AM);
								c.set(Calendar.HOUR, pmCase.getCaseDetails()
										.getAdmissionHour());
								c.set(Calendar.MINUTE, 0);
								admissionTime = c.getTime();
							}
							admissionTimeLog.setBeginTime(admissionTime);

							sm.saveRAD(admissionTimeLog);
						}
					}

					if (pmCase.getCaseDetails().getDisabilityInterval() != null) {
						AesServerUtils.saveRAD(sm, createdItemIds,
								moduleDepartment, pmCase.getCaseDetails()
										.getDisabilityInterval());
					}

					if (pmCase.getCaseDetails().getHospitalizationInterval() != null) {
						AesServerUtils.saveRAD(sm, createdItemIds,
								moduleDepartment, pmCase.getCaseDetails()
										.getHospitalizationInterval());
					}

					if (pmCase.getCaseDetails() != null) {
						AesServerUtils.saveRAD(sm, createdItemIds,
								moduleDepartment, pmCase.getCaseDetails());
					}

					for (ConditionCode code : pmCase.getCaseDetails()
							.getConditionCodes()) {
						code.setPmCaseDetails(pmCase.getCaseDetails());
						AesServerUtils.saveRAD(sm, createdItemIds,
								moduleDepartment, code);
					}

					for (OccurrenceCodeDate code : pmCase.getCaseDetails()
							.getOccurrenceCodeDates()) {
						code.setPmCaseDetails(pmCase.getCaseDetails());
						AesServerUtils.saveRAD(sm, createdItemIds,
								moduleDepartment, code);
					}

					for (OccurrenceSpanCodeDate code : pmCase.getCaseDetails()
							.getOccurrenceSpanCodeDates()) {
						code.setPmCaseDetails(pmCase.getCaseDetails());
						AesServerUtils.saveRAD(sm, createdItemIds,
								moduleDepartment, code);
					}
					// #14575
					List<ValueCodeAmount> valueCodeAmounts = new ArrayList<ValueCodeAmount>();
					valueCodeAmounts.addAll(pmCase.getCaseDetails()
							.getValueCodeAmounts());
					orderValueCodeAmounts(valueCodeAmounts, false);
					PmCaseDetails pcd = pmCase.getCaseDetails();
					if (pcd.getId() != null) {
						sm.execute(
								"DELETE FROM ValueCodeAmount vca WHERE vca.pmCaseDetails = :pcd")
								.setEntity("pcd", pcd).executeUpdate();
					}
					for (ValueCodeAmount code : valueCodeAmounts) {
						if (!code.getChangedKind().equals(ChangedKind.DELETED)) {
							code.setPmCaseDetails(pmCase.getCaseDetails());
							code.setChangedKind(ChangedKind.CREATED);
							AesServerUtils.saveRAD(sm, createdItemIds,
									moduleDepartment, code);
						}
					}
					valueCodeAmounts = null;
					// KKORNEL: AES-11687
					if (pmCase.getCaseDetails().getSupplementalInformations() != null) {
						for (SupplementalInformation supplementalInformation : pmCase
								.getCaseDetails().getSupplementalInformations()) {
							supplementalInformation.setPmCaseDetails(pmCase
									.getCaseDetails());
							AesServerUtils.saveRAD(sm, createdItemIds,
									moduleDepartment, supplementalInformation);
						}
					}
					// KKORNEL: AES-11692
					if (pmCase.getCaseDetails().getNoteInformations() != null) {
						for (NoteInformation noteInformation : pmCase
								.getCaseDetails().getNoteInformations()) {
							noteInformation.setPmCaseDetails(pmCase
									.getCaseDetails());
							AesServerUtils.saveRAD(sm, createdItemIds,
									moduleDepartment, noteInformation);
						}
					}
					//#13966
					for (PmCaseDiagnosis pmcDiag :  pmCase.getPmCaseDiagnosises()) {
						AesServerUtils.saveRAD(sm, createdItemIds, moduleDepartment, pmcDiag);
					}
					for (EciCodeCaseAssociation eciCode :  pmCase.getEciCodeCaseAssociations()) {
						AesServerUtils.saveRAD(sm, createdItemIds, moduleDepartment, eciCode);
					}
					for (PatientReasonCodeAssociation reasonCode :  pmCase.getPatientReasonCodeAssociations()) {
						AesServerUtils.saveRAD(sm, createdItemIds, moduleDepartment, reasonCode);
					}
					//#16206
					if (pmCase.getDepartment() == null) {
						pmCase.setDepartment(moduleDepartment);
					}
					AesServerUtils.saveRAD(sm, createdItemIds, moduleDepartment, pmCase);
					sm.commitTransaction();
				}
				catch (Exception e) {
					sm.rollbackTransaction();
					//#16206
					throw e;
				}
			}
		}

	}
	
	private void orderValueCodeAmounts(List<ValueCodeAmount> valueCodeAmounts, final boolean willMoveDeletedToLast) {
		Collections.sort(valueCodeAmounts, new Comparator<ValueCodeAmount>() {
			@Override
			public int compare(ValueCodeAmount o1, ValueCodeAmount o2) {
				if (o1 == null) return -1;
				if (o2 == null) return 1;
				if (willMoveDeletedToLast) {
					if (o1.getChangedKind().equals(ChangedKind.DELETED)) return 1;
				}	
				if (o1.getSequence() < o2.getSequence()) {
					return -1;
				} else if (o1.getSequence() > o2.getSequence()) {
					return 1;
				}
				return 0;
			}
		});
	}

	private PmCase loadPmCase(Long pmCaseId) throws Exception {
		PmCase result = null;
		SessionManager sm = SiteManager.Start();
		result = sm.get(PmCase.class, pmCaseId);
		RegistrationManager rm = new RegistrationManager(sm);
		rm.loadCase(result, null);

		return result;
	}

}
